package com.ticket.sass.admin.dto.output;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ticket.sass.common.entity.tenant.CouponWeekEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;

import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import java.time.DayOfWeek;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Data
@ApiModel(description = "星期时间输入模型")
public class WeekTimeOutput {
    @ApiModelProperty(value = "星期", example = "0", required = true)
    @Min(value = 0, message = "星期必须介于0到6之间")
    @Max(value = 6, message = "星期必须介于0到6之间")
    private Integer week;

    @ApiModelProperty(value = "时间段")
    private List<WeekTime> times;
    
    public WeekTimeOutput() {
    }
    
    public WeekTimeOutput(CouponWeekEntity entity) {
        this.week = entity.getWeek();
        this.times = getWeekTimes(entity.getTimes());
    }
    
    @Data
    @ApiModel(description = "优惠券有效时间段")
    public static class WeekTime {
        @ApiModelProperty(value = "开始时间", example = "08:00", required = true)
        private String start;
        
        @ApiModelProperty(value = "结束时间", example = "18:00", required = true)
        private String end;
        
        public WeekTime(String start, String end) {
            this.start = start;
            this.end = end;
        }
    }
    
    
    // 判断给定的日期时间是否匹配指定的时间段
    public static boolean isDateMatchingTimeRange(LocalDateTime dateTime, List<WeekTimeOutput> weekTimeOutputs) {
        // 获取给定日期时间的星期值，1表示周一，2表示周二，3表示周三 0 标识周日，以此类推
        int dayOfWeekValue = getCustomDayOfWeekValue(dateTime);
        
        // 检查星期值是否包含在给定的列表中
        for (WeekTimeOutput weekTimeOutput : weekTimeOutputs) {
            if (weekTimeOutput.getWeek() == dayOfWeekValue) {
                // 获取该星期对应的时间段列表
                List<WeekTimeOutput.WeekTime> timeRanges = weekTimeOutput.getTimes();
                // 检查给定日期时间是否匹配任何时间段
                return isDateTimeMatchingTimeRange(dateTime, timeRanges);
            }
        }
        return false;
    }
    
    private static int getCustomDayOfWeekValue(LocalDateTime dateTime) {
        DayOfWeek dayOfWeek = dateTime.getDayOfWeek(); // 获取星期几
        
        // 根据DayOfWeek的枚举值转换为自定义的星期数值
        return switch (dayOfWeek) {
            case SUNDAY -> 0;
            case MONDAY -> 1;
            case TUESDAY -> 2;
            case WEDNESDAY -> 3;
            case THURSDAY -> 4;
            case FRIDAY -> 5;
            case SATURDAY -> 6;
        };
    }

    
    // 判断给定的日期时间是否在指定的时间段内
    private static boolean isDateTimeMatchingTimeRange(LocalDateTime time, List<WeekTimeOutput.WeekTime> timeRanges) {
        if (timeRanges.size() == 0){
            return false;
        }
        
        for (WeekTimeOutput.WeekTime timeRange : timeRanges) {
            LocalTime startTime = parseToLocalTime(timeRange.getStart());
            LocalTime endTime = parseToLocalTime(timeRange.getEnd());
            if (!time.toLocalTime().isBefore(startTime) && !time.toLocalTime().isAfter(endTime)) {
                return true;
            }
        }
        return false;
    }
    
    private static LocalTime parseToLocalTime(String timeStr) {
        return LocalTime.parse(timeStr);
    }
    
    
    @NotNull
    public static List<WeekTimeOutput.WeekTime> getWeekTimes(String timesJson) {
        if (StringUtils.isEmpty(timesJson)) {
            return Collections.emptyList();
        }
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            List<Map<String, String>> timesList = objectMapper.readValue(timesJson, new TypeReference<>() {} );
            return timesList.stream()
                .map(timeMap -> new WeekTimeOutput.WeekTime(timeMap.get("start"), timeMap.get("end")))
                .collect(Collectors.toList());
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            return Collections.emptyList();
        }
    }

    
   
}

